package com.yifeng.repo.micro.service.server.engine.dal;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * Created by daibing on 2024/1/28.
 */
public class TransactionTargetManager {
    public static final ConcurrentMap<String, String> WRITE_TARGET = new ConcurrentHashMap<>();
    public static final ConcurrentMap<String, String> READ_TARGET = new ConcurrentHashMap<>();
    public static final ConcurrentMap<String, String> EXTRA_WRITE_TARGET = new ConcurrentHashMap<>();

    static {
        String entry = "MybatisPlus-IService";
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.save", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.saveBatch", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.saveOrUpdate", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.saveOrUpdateBatch", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.remove", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.removeById", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.removeByIds", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.removeByMap", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.removeBatchByIds", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.update", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.updateById", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.IService.updateBatchById", entry);
        EXTRA_WRITE_TARGET.put("com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.removeById", "MybatisPlus-ServiceImpl");
    }

    public static boolean containsWriteMethod(String target, boolean extra) {
        if (extra) {
            return WRITE_TARGET.containsKey(target) || EXTRA_WRITE_TARGET.containsKey(target);
        } else {
            return WRITE_TARGET.containsKey(target);
        }
    }

    public static void addWriteMethod(Set<String> targets, String entry) {
        Map<String, String> map = targets.stream().collect(Collectors.toMap(s -> s, s -> entry));
        WRITE_TARGET.putAll(map);
    }

    public static void addWriteMethod(String target, String entry) {
        WRITE_TARGET.put(target, entry);
    }

    public static Map<String, String> listWriteMethod() {
        return WRITE_TARGET.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new));
    }

    public static int writeMethodCount() {
        return WRITE_TARGET.keySet().size();
    }

    public static void addExtraWriteMethod(Set<String> targets, String entry) {
        Map<String, String> map = targets.stream().collect(Collectors.toMap(s -> s, s -> entry));
        EXTRA_WRITE_TARGET.putAll(map);
    }

    public static void addExtraWriteMethod(String target, String entry) {
        EXTRA_WRITE_TARGET.put(target, entry);
    }

    public static Map<String, String> listExtraWriteMethod() {
        return EXTRA_WRITE_TARGET.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new));
    }

    public static int extraWriteMethodCount() {
        return EXTRA_WRITE_TARGET.keySet().size();
    }

    public static boolean containsReadMethod(String target) {
        return READ_TARGET.containsKey(target);
    }

    public static void addReadMethod(Set<String> targets, String entry) {
        Map<String, String> map = targets.stream().collect(Collectors.toMap(s -> s, s -> entry));
        READ_TARGET.putAll(map);
    }

    public static void addReadMethod(String target, String entry) {
        READ_TARGET.put(target, entry);
    }

    public static Map<String, String> listReadMethod() {
        return READ_TARGET.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new));
    }

    public static int readMethodCount() {
        return READ_TARGET.keySet().size();
    }
}
